﻿// CGame.cs
// Author: Gant Briseno
#region Using Statements
using System;
using System.Collections.Generic;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
using Microsoft.Xna.Framework.Storage;
using Microsoft.Xna.Framework.GamerServices;
using Casters.source.Managers;
using Casters.source.States;
using Casters.source.Objects;
#endregion

namespace Casters.source
{
    /// <summary>
    /// This is the main type for your game
    /// </summary>
    public class CGame : Microsoft.Xna.Framework.Game
    {
        GraphicsDeviceManager graphics;
        public SpriteBatch spriteBatch;
        public Vector2 viewPort;

        // Temporary Tileset Stuff that will be located in the BattleState eventually
        public CCamera m_Camera;
        public CMouseObject m_Mouse;

        public bool bDebug = false;

        private static CGame instance = null;
        static public CGame GetInstance()
        {
            if (instance == null)
                instance = new CGame();

            return instance;
        }

        public CGame()
            : base()
        {
            graphics = new GraphicsDeviceManager(this);
            Content.RootDirectory = "Content";

            graphics.PreferredBackBufferWidth = 1280;
            graphics.PreferredBackBufferHeight = 800;

            viewPort.X = 1280;
            viewPort.Y = 800;
        }

        /// <summary>
        /// Allows the game to perform any initialization it needs to before starting to run.
        /// This is where it can query for any required services and load any non-graphic
        /// related content.  Calling base.Initialize will enumerate through any components
        /// and initialize them as well.
        /// </summary>
        protected override void Initialize()
        {
            CEventSystem.Initialize();
            CEventSystem.RegisterEventHandler(EventID.ExitGame, OnEscape);

            CRenderEngine.SetGraphicsDevice(GraphicsDevice);
            CRenderEngine.Initialize();
            CRenderEngine.SetDebugFont(Content.Load<SpriteFont>("Fonts/Arial"));

            CKeyboardManager.Initialize();

            CMouseManager.Initialize();
            CMouseManager.AddBinding(MouseDirection.Any, EventID.MouseMove);
            CMouseManager.AddBinding(MouseButtons.LeftButton, ButtonPosition.Pressed, EventID.MouseLeftClick);
            CMouseManager.AddBinding(MouseButtons.RightButton, ButtonPosition.Pressed, EventID.MouseRightClick);

            /*** Default Key Bindings ***/
            CKeyboardManager.AddBinding(Keys.Escape, ButtonPosition.Pressed, EventID.ExitGame);
            CKeyboardManager.AddBinding(Keys.Back, ButtonPosition.Pressed, EventID.Back);
            CKeyboardManager.AddBinding(Keys.Enter, ButtonPosition.Pressed, EventID.Confirm);
            CKeyboardManager.AddBinding(Keys.Up, ButtonPosition.Pressed, EventID.Up);
            CKeyboardManager.AddBinding(Keys.Down, ButtonPosition.Pressed, EventID.Down);
            CKeyboardManager.AddBinding(Keys.Left, ButtonPosition.Pressed, EventID.Left);
            CKeyboardManager.AddBinding(Keys.Right, ButtonPosition.Pressed, EventID.Right);
            CKeyboardManager.AddBinding(Keys.Up, ButtonPosition.Down, EventID.UpHeld);
            CKeyboardManager.AddBinding(Keys.Down, ButtonPosition.Down, EventID.DownHeld);
            CKeyboardManager.AddBinding(Keys.Left, ButtonPosition.Down, EventID.LeftHeld);
            CKeyboardManager.AddBinding(Keys.Right, ButtonPosition.Down, EventID.RightHeld);

            CObjectManager.Initialize();
            m_Mouse = new CMouseObject();
            
            m_Camera = new CCamera();

            CStateManager.AddState(CSplashScreenState.GetInstance());
            CUIManager.Initialize();

            base.Initialize();
        }

        /// <summary>
        /// LoadContent will be called once per game and is the place to load
        /// all of your content.
        /// </summary>
        protected override void LoadContent()
        {
            // Create a new SpriteBatch, which can be used to draw textures.
            spriteBatch = new SpriteBatch(GraphicsDevice);

            CSpellManager.GetInstance().Load("spelllist");
            CStateManager.Initialize();
            m_Mouse.LoadContent();
        }

        /// <summary>
        /// UnloadContent will be called once per game and is the place to unload
        /// all content.
        /// </summary>
        protected override void UnloadContent()
        {
            CObjectManager.ShutDown();
            CMouseManager.ClearAllBindings();
            CKeyboardManager.ClearAllBindings();
            CStateManager.Shutdown();
            CUIManager.Shutdown();
            m_Mouse.UnloadContent();
        }

        /// <summary>
        /// Allows the game to run logic such as updating the world,
        /// checking for collisions, gathering input, and playing audio.
        /// </summary>
        /// <param name="gameTime">Provides a snapshot of timing values.</param>
        protected override void Update(GameTime gameTime)
        {
            float dt = (float)gameTime.ElapsedGameTime.TotalSeconds;

            CMouseManager.Update(dt);
            CKeyboardManager.Update(dt);

            CStateManager.Update(dt);
            CObjectManager.Update(dt);
            CUIManager.Update(dt);
            m_Camera.Update(dt);

            CEventSystem.DispatchEvents();

            base.Update(gameTime);
        }

        /// <summary>
        /// This is called when the game should draw itself.
        /// </summary>
        /// <param name="gameTime">Provides a snapshot of timing values.</param>
        protected override void Draw(GameTime gameTime)
        {
            CRenderEngine.BeginBatchTransfer();

            CRenderEngine.SetBatchTransformationMatrix(m_Camera.GetTransformMatrix);

            CStateManager.Draw();

            CObjectManager.Draw();

            CUIManager.Draw();

            // Debug camera info
            if (m_Camera.m_bEnabled)
            {
                CRenderEngine.DrawString(Content.Load<SpriteFont>("Fonts/Arial"), "Camer Pos: " + m_Camera.m_vPosition.ToString(), new Vector2(10f, 100f) + m_Camera.m_vPosition, Color.Red);
                CRenderEngine.DrawString(Content.Load<SpriteFont>("Fonts/Arial"), "Camer Scale: " + m_Camera.m_fZoom.ToString(), new Vector2(10f, 135f) + m_Camera.m_vPosition, Color.Red);
            }

            m_Mouse.Draw();

            CRenderEngine.EndBatchTransfer();

            // Single thread rendering
            CRenderEngine.UpdateRenderer();

            base.Draw(gameTime);
        }

        public void OnEscape(params object[] eventArguments)
        {
            CRenderEngine.KillRenderEngine();
            Exit();
        }
    }
}
